Completed
Pull Request — develop (#125)
by Xaver
01:21
created

node.js ➔ ... ➔ V.h(ꞌaꞌ).onclick   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
c 0
b 0
f 0
nc 1
dl 0
loc 3
rs 10
nop 1
1
define(['sorttable', 'snabbdom', 'd3-interpolate', 'moment', 'helper'],
2
  function (SortTable, V, d3Interpolate, moment, helper) {
3
    'use strict';
4
5
    function showGeoURI(d) {
6
      if (!helper.hasLocation(d)) {
7
        return undefined;
8
      }
9
10
      return function (el) {
11
        var a = document.createElement('a');
12
        a.textContent = Number(d.nodeinfo.location.latitude.toFixed(6)) + ', ' + Number(d.nodeinfo.location.longitude.toFixed(6));
13
        a.href = 'geo:' + d.nodeinfo.location.latitude + ',' + d.nodeinfo.location.longitude;
14
        el.appendChild(a);
15
      };
16
    }
17
18
    function showStatus(d) {
19
      return function (el) {
20
        el.classList.add(d.flags.unseen ? 'unseen' : (d.flags.online ? 'online' : 'offline'));
21
        el.textContent = _.t((d.flags.online ? 'node.lastOnline' : 'node.lastOffline'), {
22
          time: d.lastseen.fromNow(),
23
          date: d.lastseen.format('DD.MM.YYYY, H:mm:ss')
24
        });
25
      };
26
    }
27
28
    function showFirmware(d) {
29
      var release = helper.dictGet(d.nodeinfo, ['software', 'firmware', 'release']);
30
      var base = helper.dictGet(d.nodeinfo, ['software', 'firmware', 'base']);
31
32
      if (release === null || base === null) {
33
        return undefined;
34
      }
35
36
      return release + ' / ' + base;
37
    }
38
39
    function showSite(d, config) {
40
      var site = helper.dictGet(d.nodeinfo, ['system', 'site_code']);
41
      var rt = site;
42
      if (config.siteNames) {
43
        config.siteNames.forEach(function (t) {
44
          if (site === t.site) {
45
            rt = t.name;
46
          }
47
        });
48
      }
49
      return rt;
50
    }
51
52
    function showUptime(d) {
53
      if (!('uptime' in d.statistics)) {
54
        return undefined;
55
      }
56
57
      return moment.duration(d.statistics.uptime, 'seconds').humanize();
58
    }
59
60
    function showFirstseen(d) {
61
      if (!('firstseen' in d)) {
62
        return undefined;
63
      }
64
65
      return d.firstseen.fromNow(true);
66
    }
67
68
    function showClients(d) {
69
      if (!d.flags.online) {
70
        return undefined;
71
      }
72
73
      return function (el) {
74
        el.appendChild(document.createTextNode(d.statistics.clients > 0 ? d.statistics.clients : _.t('none')));
75
        el.appendChild(document.createElement('br'));
76
77
        var span = document.createElement('span');
78
        span.classList.add('clients');
79
        span.innerHTML = '<i class="ion-person"></i>'.repeat(d.statistics.clients);
80
        el.appendChild(span);
81
      };
82
    }
83
84
    function showIPs(d) {
85
      var ips = helper.dictGet(d.nodeinfo, ['network', 'addresses']);
86
      if (ips === null) {
87
        return undefined;
88
      }
89
90
      ips.sort();
91
92
      return function (el) {
93
        ips.forEach(function (ip, i) {
94
          var link = !ip.startsWith('fe80:');
95
96
          if (i > 0) {
97
            el.appendChild(document.createElement('br'));
98
          }
99
100
          if (link) {
101
            var a = document.createElement('a');
102
            a.href = 'http://[' + ip + ']/';
103
            a.textContent = ip;
104
            el.appendChild(a);
105
          } else {
106
            el.appendChild(document.createTextNode(ip));
107
          }
108
        });
109
      };
110
    }
111
112
    function showBar(v, width, warning) {
113
      var span = document.createElement('span');
114
      span.classList.add('bar');
115
116
      var bar = document.createElement('span');
117
      bar.style.width = (width * 100) + '%';
118
      if (warning) {
119
        span.classList.add('warning');
120
      }
121
      span.appendChild(bar);
122
123
      var label = document.createElement('label');
124
      label.textContent = v;
125
      span.appendChild(label);
126
127
      return span;
128
    }
129
130
    function showLoad(d) {
131
      if (!('loadavg' in d.statistics)) {
132
        return undefined;
133
      }
134
135
      return function (el) {
136
        var value = d.statistics.loadavg.toFixed(2);
137
        var width = d.statistics.loadavg % 1;
138
        var warning = false;
139
        if (d.statistics.loadavg >= d.nodeinfo.hardware.nproc) {
140
          warning = true;
141
        }
142
        el.appendChild(showBar(value, width, warning));
143
      };
144
    }
145
146
    function showRAM(d) {
147
      if (!('memory_usage' in d.statistics)) {
148
        return undefined;
149
      }
150
151
      return function (el) {
152
        var value = Math.round(d.statistics.memory_usage * 100) + ' %';
153
        var width = d.statistics.memory_usage;
154
        var warning = false;
155
        if (d.statistics.memory_usage >= 0.8) {
156
          warning = true;
157
        }
158
        el.appendChild(showBar(value, width, warning));
159
      };
160
    }
161
162
    function showAutoupdate(d) {
163
      var au = helper.dictGet(d.nodeinfo, ['software', 'autoupdater']);
164
      if (!au) {
165
        return undefined;
166
      }
167
168
      return au.enabled ? _.t('node.activated', { branch: au.branch }) : _.t('node.deactivated');
169
    }
170
171
    function showStatImg(o, d) {
172
      var subst = {};
173
      subst['{NODE_ID}'] = d.nodeinfo.node_id ? d.nodeinfo.node_id : _.t('unknown');
174
      subst['{NODE_NAME}'] = d.nodeinfo.hostname ? d.nodeinfo.hostname.replace(/[^a-z0-9\-]/ig, '_') : _.t('unknown');
175
      subst['{TIME}'] = d.lastseen.format('DDMMYYYYHmmss');
176
      subst['{LOCALE}'] = _.locale();
177
      return helper.showStat(o, subst);
178
    }
179
180
    return function (config, el, router, d) {
181
      var linkScale = d3Interpolate.interpolate('#F02311', '#04C714');
182
      V = V.default;
183
184
      function renderNeighbourRow(n) {
185
        var icons = [];
186
        var name = [];
187
        var unknown = !(n.node);
188
189
        icons.push(V.h('span', { className: n.incoming ? 'ion-arrow-left-c' : 'ion-arrow-right-c' }));
190
        if (!unknown && helper.hasLocation(n.node)) {
191
          icons.push(V.h('span', { className: 'ion-location' }));
192
        }
193
194
        if (!unknown) {
195
          name.push(V.h('a', {
196
            props: {
197
              className: 'online',
198
              href: router.generateLink({ node: n.node.nodeinfo.node_id })
199
            }, on: {
200
              click: function (e) {
201
                router.fullUrl({ node: n.node.nodeinfo.node_id }, e);
202
              }
203
            }
204
          }, n.node.nodeinfo.hostname));
205
        } else {
206
          name.push(n.link.id);
207
        }
208
209
        var td1 = V.h('td', icons);
210
        var td2 = V.h('td', name);
211
        var td3 = V.h('td', (n.node.statistics.clients ? n.node.statistics.clients.toString() : '0'));
212
        var td4 = V.h('td', { style: { color: linkScale(1 / n.link.tq) } }, helper.showTq(n.link));
213
        var td5 = V.h('td', helper.showDistance(n.link));
214
215
        return V.h('tr', [td1, td2, td3, td4, td5]);
216
      }
217
218
      var h2 = document.createElement('h2');
219
      h2.textContent = d.nodeinfo.hostname;
220
      el.appendChild(h2);
221
222
      var attributes = document.createElement('table');
223
      attributes.classList.add('attributes');
224
225
      helper.attributeEntry(attributes, 'node.status', showStatus(d));
226
      helper.attributeEntry(attributes, 'node.gateway', d.flags.gateway ? 'ja' : null);
227
      helper.attributeEntry(attributes, 'node.coordinates', showGeoURI(d));
228
229
      if (config.nodeInfobox && config.nodeInfobox.contact) {
230
        helper.attributeEntry(attributes, 'node.contact', helper.dictGet(d.nodeinfo, ['owner', 'contact']));
231
      }
232
233
      helper.attributeEntry(attributes, 'node.hardware', helper.dictGet(d.nodeinfo, ['hardware', 'model']));
234
      helper.attributeEntry(attributes, 'node.primaryMac', helper.dictGet(d.nodeinfo, ['network', 'mac']));
235
      helper.attributeEntry(attributes, 'node.id', helper.dictGet(d.nodeinfo, ['node_id']));
236
      helper.attributeEntry(attributes, 'node.firmware', showFirmware(d));
237
      helper.attributeEntry(attributes, 'node.site', showSite(d, config));
238
      helper.attributeEntry(attributes, 'node.uptime', showUptime(d));
239
      helper.attributeEntry(attributes, 'node.firstSeen', showFirstseen(d));
240
      if (config.nodeInfobox && config.nodeInfobox.hardwareUsage) {
241
        helper.attributeEntry(attributes, 'node.systemLoad', showLoad(d));
242
        helper.attributeEntry(attributes, 'node.ram', showRAM(d));
243
      }
244
      helper.attributeEntry(attributes, 'node.ipAddresses', showIPs(d));
245
      helper.attributeEntry(attributes, 'node.selectedGateway', helper.dictGet(d.statistics, ['gateway']));
246
      helper.attributeEntry(attributes, 'node.update', showAutoupdate(d));
247
      helper.attributeEntry(attributes, 'node.clients', showClients(d));
248
249
      el.appendChild(attributes);
250
251
      if (d.neighbours.length > 0) {
252
        var h3 = document.createElement('h3');
253
        h3.textContent = _.t('node.link', d.neighbours.length) + '(' + d.neighbours.length + ')';
254
        el.appendChild(h3);
255
256
        var headings = [{
257
          name: ''
258
        }, {
259
          name: 'node.nodes',
260
          sort: function (a, b) {
261
            return a.node.nodeinfo.hostname.localeCompare(b.node.nodeinfo.hostname);
262
          },
263
          reverse: false
264
        }, {
265
          name: 'node.clients',
266
          class: 'ion-people',
267
          sort: function (a, b) {
268
            return ('clients' in a.node.statistics ? a.node.statistics.clients : -1) -
269
              ('clients' in b.node.statistics ? b.node.statistics.clients : -1);
270
          },
271
          reverse: true
272
        }, {
273
          name: 'node.tq',
274
          class: 'ion-connection-bars',
275
          sort: function (a, b) {
276
            return a.link.tq - b.link.tq;
277
          },
278
          reverse: true
279
        }, {
280
          name: 'node.distance',
281
          class: 'ion-arrow-resize',
282
          sort: function (a, b) {
283
            return (a.link.distance === undefined ? -1 : a.link.distance) -
284
              (b.link.distance === undefined ? -1 : b.link.distance);
285
          },
286
          reverse: true
287
        }];
288
289
        var table = new SortTable(headings, 1, renderNeighbourRow);
290
        table.el.classList.add('node-links');
291
        table.setData(d.neighbours);
292
293
        el.appendChild(table.el.elm);
294
      }
295
296
      if (config.nodeInfos) {
297
        config.nodeInfos.forEach(function (nodeInfo) {
298
          var h4 = document.createElement('h4');
299
          h4.textContent = nodeInfo.name;
300
          el.appendChild(h4);
301
          el.appendChild(showStatImg(nodeInfo, d));
302
        });
303
      }
304
    };
305
  });
306